This document will detail how to use Vivado 2021 and Vitis 2021 to display four color bars on a computer monitor via an HDMI interface by configuring hardware, software, and pin constraints. The explanation will be supplemented with the provided project module hardware design diagrams, experimental result images, and a system block diagram.
Processor System Reset Module
Function: This module is used to generate and manage system reset signals. It ensures that during system startup and operation, all modules can be reset with the correct timing, preventing system instability.
AXI Interconnect Module
Function: The AXI Interconnect module is used to connect multiple AXI (Advanced eXtensible Interface) bus devices. It facilitates data and control signal transmission between multiple master and slave devices, ensuring that data flows correctly between different modules.
AXI Video Direct Memory Access Module
Function: This module performs Direct Memory Access (DMA) operations between video data and memory. It efficiently handles video data transfer, reducing the CPU's workload and improving system performance.
Video Timing Controller Module
Function: The Video Timing Controller module is responsible for generating video timing signals, such as horizontal sync, vertical sync, and pixel clock. These signals are crucial for correctly displaying video data on a monitor.
VDMA Module
Function: The VDMA (Video DMA) module is used for high-speed data transfer between video data and system memory. It can read video data from memory according to the timing signals generated by the Video Timing Controller and transmit it to the display.
The system block diagram is as follows:
PS (Processing System) Section
ARM Cortex-A9: This is the main processor of the system, responsible for running software programs and controlling the overall system operation.
HP and GP Interfaces: These interfaces are used to connect various peripherals, enabling the transmission of data and control signals.
DDR Memory: Used to store the programs and data required for system operation, providing high-speed data storage and access capabilities.
PL (Programmable Logic) Section
VDMA: Has the same function as the VDMA module mentioned earlier, responsible for video data memory access.
Video Timing Controller: Generates video timing signals to ensure correct video data display.
AXI-Stream to DVI Transmitter: This module converts video data from AXI-Stream format to DVI (Digital Visual Interface) format for transmission to the monitor via the HDMI interface.
HDMI Display: Used to display the final video output.
Package the HDMI driver section into an IP core for direct import later.
On the basis of the previous hardware design, we need to add the ZYNQ IP core design:
The IP core after configuration:
Search for the VDMA core and configure it as shown in the figure below:
Search for the timing core and configure it as shown in the figure below:
Search for the video out core and configure it as shown in the figure below:
Search for the clock core and configure it as shown in the figure below:
Add the custom IP: dvi_transmitter. This IP core is located in the ip_repo folder within the project directory.
After adding it, connect and expose the external ports (only the TMDS port needs to be exposed). Connect pclk_x5 to the clkout2 of the clock output from the previous step.
Make the connections, then click "Run Connection Automation". The modules and their interfaces that will be automatically connected are listed below. Check "All Automation" and then click the "OK" button. The system will then automatically generate two AXI Interconnect modules (axi_mem_intercon and ps7_0_axi_periph). Additionally, the system will also automatically generate one reset module (rst_ps7_0_150M) to reset the peripherals on the bus.
After modifying the block design, save it, then regenerate Output Products and "Create HDL Wrapper". Next, we need to modify the constraints file to assign pins for the HDMI interface according to the schematic.
Save the constraints file, then proceed with the subsequent steps to regenerate the BIT file.
Right-click the created platform project, click "Update Hardware Specification", select the .xsa file path. The following dialog box will appear; click OK, which indicates a successful update. Good practice: After updating, right-click the platform project again and select "Build".
Write code in the software project. In the software code, define the data for four color bars (red, green, blue, white). Implement the generation and transmission of this data.
Store this color bar data in DDR memory and transfer it to the display via the VDMA module.
x
//VDMA device ID//VTC device ID
XAxiVdma vdma;DisplayCtrl dispCtrl;VideoMode vd_mode;
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
int main(void){ xil_printf("HDMI Display 1920*1080 \r\n");
//set video parameters, resolution: 1920*1080 vd_mode = VMODE_1920x1080;
//configure VDMA run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height, frame_buffer_addr,0, 0,ONLY_READ);
//initialize Display controller DisplayInitialize(&dispCtrl, DISP_VTC_ID); //set VideoMode DisplaySetMode(&dispCtrl, &vd_mode); DisplayStart(&dispCtrl);
int y = 0; int x = 0; for(y = 0; y < vd_mode.height; y++) { for(x = 0; x < vd_mode.width; x++) if (x >= 0 && x < (vd_mode.width / 4) * 1) { // white *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0xff; } else if (x >= (vd_mode.width/4)*1 && x < (vd_mode.width/4)*2) { // red *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0xff;
} else if (x >= (vd_mode.width/4)*2 && x < (vd_mode.width/4)*3) { // green *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0x00; } else { // blue *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+0)=0xff; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+1)=0x00; *((u8 *)frame_buffer_addr+y*vd_mode.width*3+3*x+2)=0x00; } }
Xil_DCacheFlush(); //flush Cache,update data to DDR while(1) {
} return 0; }
After successfully compiling the project, connect the development board's JTAG to the computer using a Type-C USB cable. Use another Type-C USB cable to connect the board's PS UART to the computer. Use an HDMI cable to connect the board's HDMI output port to the computer monitor's HDMI input port.
On the computer, open the serial debugging tool MobaXterm and establish a connection with the development board's PS UART.
Enter debug mode in Vitis: Under "Debug As", select the first option. Running at full speed will allow you to see the debug information through the serial port.
The debugging results are as follows:
The running results are as follows: